#pragma once	

#ifndef Affects_h
#define Affects_h

#include "Standards.h"
#include "StmtTable.h"
#include "VarTable.h"
#include "Modifies.h"
#include "Uses.h"
#include "CFG.h"
#include "Schema.h"

/*! Affects Class */
class Affects {
	public:
		StmtTable* myST; //!< StmtTable pointer
		VarTable* myVT; //!< VarTable pointer
		Modifies* myM;
		Uses* myU;
		CFG* myCFG;
		unordered_multimap<INDEX, INDEX> followsTableStmt; //!< Affects table
		unordered_multimap<INDEX, INDEX> followsTableStmtClosure; //!< Affects table
		//! Constructor (takes in the VarTable and stmtTable)
		Affects(VarTable*, StmtTable*, Modifies*, Uses*, CFG*);
		set<INDEX> recurseFinal;
		void recursive(INDEX,INDEX,NAME,INDEX,INDEX);
		/*! 
		  A method that computes and stores the transitive closures
		*/
		void computeClosure();

		/*! 
		  A method that prints the contents of the Parent table
		*/
		void printAll();

		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(s1,s2)
		  \param DESIGN_ENTITY design-entity of s1
		  \param NAME s1
		  \param DESIGN_ENTITY design-entity of s2
		  \param NAME s2
		*/
		Schema getSynSyn(DESIGN_ENTITY,NAME,DESIGN_ENTITY,NAME);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(s1,3)
		  \param DESIGN_ENTITY design-entity of s1
		  \param NAME s1
		  \param INDEX 3
		*/
		Schema getSynInt(DESIGN_ENTITY,NAME,INDEX);
		

		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(s1,_)
		  \param DESIGN_ENTITY design-entity of s1
		  \param NAME s1
		*/
		Schema getSynUnd(DESIGN_ENTITY,NAME);

		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(3,s2)
		  \param INDEX 3
		  \param DESIGN_ENTITY design-entity of s2
		  \param NAME s2
		*/
		Schema getIntSyn(INDEX,DESIGN_ENTITY,NAME);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(3,4)
		  \param INDEX 3
		  \param INDEX 4
		*/
		Schema getIntInt(INDEX,INDEX);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(3,_)
		  \param INDEX 3
		*/
		Schema getIntUnd(INDEX);

		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(_,3)
		  \param INDEX 3
		*/
		Schema getUndInt(INDEX);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(_,s2)
		  \param DESIGN_ENTITY design-entity of s2
		  \param NAME s2
		*/
		Schema getUndSyn(DESIGN_ENTITY,NAME);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(_,_) 
		*/
		Schema getUndUnd();


		//.........................................

				//...Closure...

		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(s1,s2)
		  \param DESIGN_ENTITY design-entity of s1
		  \param NAME s1
		  \param DESIGN_ENTITY design-entity of s2
		  \param NAME s2
		*/
		Schema getSynSynClosure(DESIGN_ENTITY,NAME,DESIGN_ENTITY,NAME);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(s1,3)
		  \param DESIGN_ENTITY design-entity of s1
		  \param NAME s1
		  \param INDEX 3
		*/
		Schema getSynIntClosure(DESIGN_ENTITY,NAME,INDEX);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(s1,_)
		  \param DESIGN_ENTITY design-entity of s1
		  \param NAME s1
		*/
		Schema getSynUndClosure(DESIGN_ENTITY,NAME);

		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(3,s2)
		  \param INDEX 3
		  \param DESIGN_ENTITY design-entity of s2
		  \param NAME s2
		*/
		Schema getIntSynClosure(INDEX,DESIGN_ENTITY,NAME);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(3,4)
		  \param INDEX 3
		  \param INDEX 4
		*/
		Schema getIntIntClosure(INDEX,INDEX);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(3,_)
		  \param INDEX 3
		*/
		Schema getIntUndClosure(INDEX);

		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(_,3)
		  \param INDEX 3
		*/
		Schema getUndIntClosure(INDEX);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(_,s2)
		  \param DESIGN_ENTITY design-entity of s2
		  \param NAME s2
		*/
		Schema getUndSynClosure(DESIGN_ENTITY,NAME);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Affects(_,_) 
		*/
		Schema getUndUndClosure();

	private:
		int count; //!< Size of Affects table
};

#endif